package com.bizmda.bizsip.app.controller;

import cn.hutool.core.text.StrFormatter;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.bizmda.bizsip.app.checkrule.*;
import com.bizmda.bizsip.app.config.CheckRuleConfigMapping;
import com.bizmda.bizsip.common.*;
import com.bizmda.bizsip.app.config.AppServiceMapping;
import com.bizmda.bizsip.app.executor.AbstractAppExecutor;
import com.bizmda.bizsip.service.AppLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * @author 史正烨
 */
@Slf4j
@RestController
//@RequestMapping("/")
public class AppController {
    @Autowired
    private AppServiceMapping appServiceMapping;
    @Autowired
    private CheckRuleConfigMapping checkRuleConfigMapping;
    @Autowired
    private AppLogService appLogService;

    @PostMapping(value="/api",consumes = "application/json", produces = "application/json")
    public BizMessage<JSONObject> doApiService(HttpServletRequest request, HttpServletResponse response,
                                               @RequestBody JSONObject inJsonObject,
                                               @PathVariable(required = false) Map<String, Object> pathVariables,
                                               @RequestParam(required = false) Map<String, Object> parameters) throws BizException {
        String serviceId = request.getHeader("Biz-Service-Id");
        log.debug("开始处理App服务: {}",serviceId);
        log.trace("App服务[{}]请求报文:\n{}",serviceId,BizUtils.buildJsonLog(inJsonObject));
        BizMessage<JSONObject> bizMessage = BizMessage.createNewTransaction(serviceId);
        bizMessage.setData(inJsonObject);
        BizTools.bizMessageThreadLocal.set(bizMessage);
        BizMessage<JSONObject> inMessage = BizTools.copyBizMessage(bizMessage);

        JSONArray jsonArray = this.checkFieldRule(serviceId,inJsonObject);
        if (!jsonArray.isEmpty()) {
            throw new BizException(BizResultEnum.CHECKRULE_FIELD_CHECK_ERROR,jsonArray.toString());
        }

        jsonArray = this.checkServiceRule(serviceId,inJsonObject);
        if (!jsonArray.isEmpty()) {
            throw new BizException(BizResultEnum.CHECKRULE_SERVICE_CHECK_ERROR,jsonArray.toString());
        }

        AbstractAppExecutor appExecutor = this.appServiceMapping.getAppExecutor(serviceId);
        if (appExecutor == null) {
            log.error("App服务[{}]不存在",serviceId);
            throw new BizException(BizResultEnum.APP_SERVICE_NOT_FOUND,
                    StrFormatter.format("App服务[{}]不存在",serviceId));
        }

        BizTools.tmContextThreadLocal.set(new TmContext());
        BizTools.serviceIdThreadLocal.set(serviceId);
        BizMessage<JSONObject> outMessage = null;
        log.debug("调用App服务[{}]: traceId={}",serviceId,bizMessage.getTraceId());
        try {
            outMessage = appExecutor.doAppService(bizMessage);
        }
        catch (Exception e) {
            log.error("App服务执行出错",e);
            outMessage = BizMessage.buildFailMessage(bizMessage,e);
        }
        finally {
            BizTools.tmContextThreadLocal.remove();
            BizTools.bizMessageThreadLocal.remove();
            BizTools.serviceIdThreadLocal.remove();
        }
        if (outMessage.getCode() == 0) {
            log.debug("发送交易成功日志");
            this.appLogService.sendAppSuccessLog(inMessage,outMessage);
        }
        else {
            log.debug("发送交易失败日志");
            this.appLogService.sendAppFailLog(inMessage,outMessage);
        }
        return outMessage;
    }

    private JSONArray checkFieldRule(String serviceId, JSONObject message) throws BizException {
        JSONArray jsonArray = new JSONArray();
        CheckRuleConfig checkRuleConfig = this.checkRuleConfigMapping.getCheckRuleConfig(serviceId);
        if (checkRuleConfig == null) {
            return jsonArray;
        }
        List<FieldCheckRule> fieldCheckRuleList = checkRuleConfig.getFieldCheckRuleList();
        if (fieldCheckRuleList == null) {
            return jsonArray;
        }
        log.debug("开始App服务[{}]域级规则校验",serviceId);

        List<FieldChcekRuleResult> fieldChcekRuleResultList = FieldCheckRuleHelper.checkFieldRule(message, fieldCheckRuleList,checkRuleConfig.getFieldCheckMode());

        for(FieldChcekRuleResult fieldChcekRuleResult:fieldChcekRuleResultList) {
            log.warn("域级校验规则不通过:{}-{}",fieldChcekRuleResult.getField(),
                    fieldChcekRuleResult.getMessage());
            JSONObject jsonObject = new JSONObject();
            jsonObject.set("field", fieldChcekRuleResult.getField());
            jsonObject.set("message", fieldChcekRuleResult.getMessage());
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }

    private JSONArray checkServiceRule(String serviceId, JSONObject message) throws BizException {
        JSONArray jsonArray = new JSONArray();
        CheckRuleConfig checkRuleConfig = this.checkRuleConfigMapping.getCheckRuleConfig(serviceId);
        if (checkRuleConfig == null) {
            return jsonArray;
        }
        List<ServiceCheckRule> serviceCheckRuleList = checkRuleConfig.getServiceCheckRuleList();
        if (serviceCheckRuleList == null) {
            return jsonArray;
        }
        log.debug("开始App服务[{}]服务级规则校验",serviceId);

        List<ServiceChcekRuleResult> serviceChcekRuleResultList = ServiceCheckRuleHelper.checkServiceRule(message, serviceCheckRuleList,checkRuleConfig.getFieldCheckMode());

        for(ServiceChcekRuleResult serviceChcekRuleResult:serviceChcekRuleResultList) {
            log.warn("服务级校验规则不通过:{}",serviceChcekRuleResult.getResult());
            JSONObject jsonObject = new JSONObject();
            jsonObject.set("message", serviceChcekRuleResult.getResult());
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }

}
